package com.cloud.service.impl;

import cn.hutool.core.date.DateUtil;
import com.cloud.entity.mes.*;
import com.cloud.feign.resp.*;
import com.cloud.mapper.*;
import com.cloud.service.AccessoryTraceabilityService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author admin
 */
@Service
@Slf4j
public class AccessoryTraceabilityServiceImpl implements AccessoryTraceabilityService {

    private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    @Autowired
    private MesSysBarCodeMapper mesSysBarCodeMapper;
    @Autowired
    private MesPmcProduceTaskMapper mesPmcProduceTaskMapper;
    @Autowired
    private MesProductBindMapper mesProductBindMapper;
    @Autowired
    private MesPcbBoxCodeBindMapper mesPcbBoxCodeBindMapper;
    @Autowired
    private MesPcbBarCodeMapper mesPcbBarCodeMapper;
    @Autowired
    private MesPcbProduceTaskMapper mesPcbProduceTaskMapper;
    @Autowired
    private MesSysBoxCodeBindMapper mesSysBoxCodeBindMapper;
    @Autowired
    private MesQmProductExamMapper mesQmProductExamMapper;
    @Autowired
    private MesQmTestProcessMapper mesQmTestProcessMapper;
    @Autowired
    private MesQmRepairMapper mesQmRepairMapper;
    @Autowired
    private MesQmMaintenanceDtlMapper mesQmMaintenanceDtlMapper;
    @Autowired
    private MesQmMaintenanceMapper mesQmMaintenanceMapper;
    @Autowired
    private MesPcbCompleteMapper mesPcbCompleteMapper;
    @Autowired
    private MesSysJyMaterialMapper mesSysJyMaterialMapper;
    @Autowired
    private MesPcbProductContrastMapper mesPcbProductContrastMapper;
    @Autowired
    private MesSysProductContrastMapper mesSysProductContrastMapper;
    @Autowired
    private MesQmInComingItemMapper mesQmInComingItemMapper;

    @Override
    public ProductBasicInfo getProductBasicInfo(String barCode) {
        ProductBasicInfo res = new ProductBasicInfo();
        // 1、获取九阳物料编码和物料名称
        MesSysBarCode mesSysBarCode = mesSysBarCodeMapper.queryByBarCode(barCode);
        if (mesSysBarCode == null) {
            log.error("查询MesSysBarCode结果为空：{}", barCode);
            return null;
        }
        if (StringUtils.isNotBlank(mesSysBarCode.getTaskid())) {
            MesPmcProduceTask result = mesPmcProduceTaskMapper.getMesPmcProduceTaskById(mesSysBarCode.getTaskid());
            if (result == null) {
                log.info("查询MesPmcProduceTask结果为空，id：{}", mesSysBarCode.getTaskid());
            } else {
                res.setProductName(result.getProductname());
                res.setProductCode(result.getProductcode());
            }
        }
        res.setBarcode(barCode);
        return res;
    }

    public KeyAccessoryInfo getKeyAccessoryInfo(String barcode) {
        KeyAccessoryInfo keyAccessoryInfo = new KeyAccessoryInfo();
        // 1 获取配件码信息
        List<MesProductBind> productBindInfoList = mesProductBindMapper.getProductBindInfoList(barcode);
        if (CollectionUtils.isEmpty(productBindInfoList)) {
            return null;
        }
        String completeMachineFactoryId = productBindInfoList.get(0).getFactoryId();
        List<String> snCodeList = productBindInfoList.stream().map(MesProductBind::getSnCode).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(snCodeList)) {
            return null;
        }
        // 2 获取质检信息
        List<KeyAccessoryQualityInfo> keyAccessoryQualityInfoList = new ArrayList<>();
        List<MesPcbBoxCodeBind> mesPcbBoxCodeBindList = mesPcbBoxCodeBindMapper.getAccessoryBoxCodeBySncode(snCodeList);
        if (!CollectionUtils.isEmpty(mesPcbBoxCodeBindList)) {
            Set<String> boxCodeSet = mesPcbBoxCodeBindList.stream().map(MesPcbBoxCodeBind::getBoxcode).collect(Collectors.toSet());
            for (String boxCode : boxCodeSet) {
                String supplier = boxCode.substring(6, 13);
                log.info("箱码是{}，对应的供应商是{}", boxCode, supplier);
                //
                MesQmInComingItem mesQmInComingItem = mesQmInComingItemMapper.getInComingItem(boxCode, completeMachineFactoryId, supplier);

                if (mesQmInComingItem != null) {
                    KeyAccessoryQualityInfo keyAccessoryQualityInfo = new KeyAccessoryQualityInfo();
                    keyAccessoryQualityInfo.setBatchNum(mesQmInComingItem.getCode());
                    keyAccessoryQualityInfo.setInComingCode(mesQmInComingItem.getColumn22());
                    keyAccessoryQualityInfo.setProductCode(mesQmInComingItem.getProductCode());
                    keyAccessoryQualityInfo.setProductName(mesQmInComingItem.getProductName());
                    if (mesQmInComingItem.getAmount() != null) {
                        keyAccessoryQualityInfo.setNumber(mesQmInComingItem.getAmount().intValue());
                    }
                    keyAccessoryQualityInfo.setFactoryName(mesQmInComingItem.getSupplierName());
                    keyAccessoryQualityInfo.setTestResult(mesQmInComingItem.getTestResult());
                    keyAccessoryQualityInfoList.add(keyAccessoryQualityInfo);
                }

            }
        }
        keyAccessoryInfo.setProductAccessoryExams(keyAccessoryQualityInfoList);

        // 找到SN码对应的九阳物料信息
        List<SnCodeDetail> snCodeDetails = new ArrayList<>();

        // 3 获取关键配件组装信息
        List<KeyAccessoryAssembleInfo> keyAccessoryAssembleInfoList = new ArrayList<>();

        List<MesPcbBarCode> mesPcbBarCodeBySnCodes = mesPcbBarCodeMapper.getMesPcbBarCodeBySnCodes(snCodeList);
        if (CollectionUtils.isNotEmpty(mesPcbBarCodeBySnCodes)) {
            Set<String> taskIdSet = mesPcbBarCodeBySnCodes.stream().map(MesPcbBarCode::getTaskId).collect(Collectors.toSet());
            Map<String, String> productFactoryMap = mesPcbBarCodeBySnCodes.stream().filter(
                    x -> StringUtils.isNotBlank(x.getSnCode())).collect(Collectors.toMap(MesPcbBarCode::getSnCode, x -> x.getProductCode() + "$" + x.getFactoryId()));
            //封装请求参数
            List<String> factoryReq = new ArrayList<>();
            List<String> productReq = new ArrayList<>();

            List<MesPcbProduceTask> mesPcbProduceTaskList = mesPcbProduceTaskMapper.getListByIds(new ArrayList<>(taskIdSet));
            Map<String, MesPcbProduceTask> mesPcbProduceTaskMap = mesPcbProduceTaskList.stream().filter(
                    x -> StringUtils.isNotBlank(x.getId())).collect(Collectors.toMap(x -> x.getId(), x -> x, (x, y) -> x));
            for (MesPcbBarCode mesPcbBarCode : mesPcbBarCodeBySnCodes) {
                MesPcbProduceTask task = mesPcbProduceTaskMap.get(mesPcbBarCode.getTaskId());
                KeyAccessoryAssembleInfo keyAccessoryAssembleInfo = new KeyAccessoryAssembleInfo();
                keyAccessoryAssembleInfo.setSnCode(mesPcbBarCode.getSnCode());
                keyAccessoryAssembleInfo.setFactoryName(task.getFactoryName());
                keyAccessoryAssembleInfo.setTaskCode(task.getCode());
                keyAccessoryAssembleInfo.setProductCode(task.getProductCode());
                keyAccessoryAssembleInfo.setProductName(task.getProductName());
                keyAccessoryAssembleInfoList.add(keyAccessoryAssembleInfo);

                //封装请求参数
                productReq.add(mesPcbBarCode.getProductCode());
                factoryReq.add(mesPcbBarCode.getFactoryId());
            }


            List<MesPcbProductContrast> mesPcbProductContrastList = mesPcbProductContrastMapper.getProductCodeList(productReq, factoryReq);
            List<MesSysProductContrast> mesSysProductContrastList = mesSysProductContrastMapper.getProductCodeList(productReq, factoryReq);

            Map<String, String> mesPcbProductContrastMap = mesPcbProductContrastList.stream().filter(
                    x -> StringUtils.isNotBlank(x.getJyProductCode())).collect(Collectors.toMap(x -> x.getPcbProductCode() + "$" + x.getFactoryId(), MesPcbProductContrast::getJyProductCode));
            Map<String, String> mesSysProductContrastMap = mesSysProductContrastList.stream().filter(
                    x -> StringUtils.isNotBlank(x.getJproductcode())).collect(Collectors.toMap(x -> x.getOproductcode() + "$" + x.getFactoryid(), MesSysProductContrast::getJproductcode));

            Map<String, String> productMap = new HashMap();
            productMap.putAll(mesPcbProductContrastMap);
            productMap.putAll(mesSysProductContrastMap);

            List<MesSysJyMaterial> mesSysJyMaterialList = mesSysJyMaterialMapper.getListByCode(productMap.values().stream().collect(Collectors.toList()));
            Map<String, MesSysJyMaterial> mesSysJyMaterialMap = mesSysJyMaterialList.stream().filter(
                    x -> StringUtils.isNotBlank(x.getCode())).collect(Collectors.toMap(x -> x.getCode(), x -> x, (x, y) -> x));

            for (MesPcbBarCode mesPcbBarCode : mesPcbBarCodeBySnCodes) {
                SnCodeDetail detail = new SnCodeDetail();
                detail.setSnCode(mesPcbBarCode.getSnCode());
                if (StringUtils.isNotBlank(productFactoryMap.get(mesPcbBarCode.getSnCode()))) {
                    String a = productFactoryMap.get(mesPcbBarCode.getSnCode());
                    if (StringUtils.isNotBlank(productMap.get(a))) {
                        String b = productMap.get(a);
                        if (mesSysJyMaterialMap.get(b) != null) {
                            detail.setItemCode(mesSysJyMaterialMap.get(b).getCode());
                            detail.setItemName(mesSysJyMaterialMap.get(b).getName());
                        }
                    }
                }
                snCodeDetails.add(detail);
            }
        }
        Map<String, SnCodeDetail> snCodeDetailMap = snCodeDetails.stream().filter(x -> StringUtils.isNotBlank(x.getItemCode())).collect(Collectors.toMap(x -> x.getSnCode(), x -> x, (x, y) -> x));
        Map<String, MesProductBind> productBindInfoMap = productBindInfoList.stream().collect(Collectors.toMap(MesProductBind::getSnCode, x -> x, (x, y) -> x));
        for (KeyAccessoryAssembleInfo keyAccessoryAssembleInfo : keyAccessoryAssembleInfoList) {
            keyAccessoryAssembleInfo.setProductBarCode(barcode);
            MesProductBind mesProductBind = productBindInfoMap.get(keyAccessoryAssembleInfo.getSnCode());
            if (mesProductBind != null) {
                if (mesProductBind.getDeleted() == 0) {
                    keyAccessoryAssembleInfo.setStatus("正常");
                } else {
                    keyAccessoryAssembleInfo.setStatus("维修更换");
                }
                keyAccessoryAssembleInfo.setBindTime(DateUtil.formatDateTime(mesProductBind.getCdTime()));
            }
            SnCodeDetail snDetail = snCodeDetailMap.get(keyAccessoryAssembleInfo.getSnCode());
            if (snDetail != null) {
                keyAccessoryAssembleInfo.setProductCode(snDetail.getItemCode());
                keyAccessoryAssembleInfo.setProductName(snDetail.getItemName());
            }
        }
        keyAccessoryInfo.setProductAccessoryAssembles(keyAccessoryAssembleInfoList);
        return keyAccessoryInfo;
    }

    public ManufacturingProcessInfo getManufacturingProcess(String barCode) {
        ManufactureBasicInfo basicInfo = new ManufactureBasicInfo();
        // 1、获取产品码对应的工单号

        MesSysBarCode mesSysBarCode = mesSysBarCodeMapper.queryByBarCode(barCode);
        if (mesSysBarCode == null) {
            log.error("查询MesSysBarCode结果为空：{}", barCode);
            return null;
        }

        MesPmcProduceTask mesPmcProduceTask = mesPmcProduceTaskMapper.getMesPmcProduceTaskById(mesSysBarCode.getTaskid());
        if (mesPmcProduceTask == null) {
            log.error("产品码{}错误", barCode);
            return null;
        }

        basicInfo.setFactoryId(mesPmcProduceTask.getFactoryid());
        basicInfo.setWorkShopName(mesPmcProduceTask.getWorkshopname());
        basicInfo.setFactoryName(mesPmcProduceTask.getFactoryname());
        basicInfo.setTaskCode(mesPmcProduceTask.getCode());

        MesSysBoxCodeBind produceTimeByCode = mesSysBoxCodeBindMapper.getProduceTimeByCode(barCode);
        if (produceTimeByCode != null && produceTimeByCode.getCdtime() != null) {
            basicInfo.setProduceTime(sdf.format(produceTimeByCode.getCdtime()));
        }

        List<ProductExam> productExams = new ArrayList<>();
        // 2、获取质检信息
        // 2.1、获取首件和巡查检验数据
        MesQmTestProcess mesQmTestProcess0 = mesQmTestProcessMapper.getQmTestProcess(mesPmcProduceTask, 0);
        MesQmTestProcess mesQmTestProcess1 = mesQmTestProcessMapper.getQmTestProcess(mesPmcProduceTask, 1);

        if (mesQmTestProcess0 != null) {
            ProductExam productExam0 = new ProductExam();
            productExam0.setExamNo(mesQmTestProcess0.getCode());
            productExam0.setTestResult(mesQmTestProcess0.getTestResult());
            productExam0.setExamUserName(mesQmTestProcess0.getTestUserName());
            if (mesQmTestProcess0.getTestDate() != null) {
                productExam0.setExamTime(sdf.format(mesQmTestProcess0.getTestDate()));
            }
            productExam0.setExamType("0");
            productExams.add(productExam0);
        }

        if (mesQmTestProcess1 != null) {
            ProductExam productExam1 = new ProductExam();
            productExam1.setExamNo(mesQmTestProcess0.getCode());
            productExam1.setTestResult(mesQmTestProcess0.getTestResult());
            productExam1.setExamUserName(mesQmTestProcess0.getTestUserName());
            if (mesQmTestProcess0.getTestDate() != null) {
                productExam1.setExamTime(sdf.format(mesQmTestProcess0.getTestDate()));
            }
            productExam1.setExamType("1");
            productExams.add(productExam1);
        }
        // 2.2、获取成品检验和验货检验数据
        // 获取检验单ID

        MesQmProductExam mesQmProductExam = mesQmProductExamMapper.getProductExamById(produceTimeByCode.getExamid());

        if (mesQmProductExam != null) {
            basicInfo.setExamNo(mesQmProductExam.getCode());
            if (mesQmProductExam.getStestDate() != null) {
                basicInfo.setExamTime(sdf.format(mesQmProductExam.getStestDate()));
            }

            ProductExam processOfTwo = new ProductExam();
            processOfTwo.setExamType("2");
            processOfTwo.setExamNo(mesQmProductExam.getCode());
            processOfTwo.setTestResult(mesQmProductExam.getStestResult());
            if (mesQmProductExam.getStestDate() != null) {
                processOfTwo.setExamTime(sdf.format(mesQmProductExam.getStestDate()));
            }

            processOfTwo.setExamUserName(mesQmProductExam.getStestUserName());
//            processOfTwo.setExamFile(mesQmProductExam.getUrl());
            productExams.add(processOfTwo);
            if (!StringUtils.isEmpty(mesQmProductExam.getJtestResult())) {
                ProductExam processOfThree = new ProductExam();
                processOfThree.setExamType("3");
                processOfThree.setExamNo(mesQmProductExam.getCode());
                processOfThree.setTestResult(mesQmProductExam.getJtestResult());
                if (mesQmProductExam.getJtestDate() != null) {
                    processOfTwo.setExamTime(sdf.format(mesQmProductExam.getJtestDate()));
                }
                processOfThree.setExamUserName(mesQmProductExam.getJtestUserName());
//                processOfThree.setExamFile(productExamInfo.getUrl());
                productExams.add(processOfThree);
            }
        }

        List<ProductRepair> productRepairList = new ArrayList<>();

        List<MesQmMaintenance> mesQmMaintenanceList = mesQmMaintenanceMapper.getListByBarcode(barCode);
        if (CollectionUtils.isNotEmpty(mesQmMaintenanceList)) {
            Map<Integer, MesQmMaintenance> snCodeDetailMap = mesQmMaintenanceList.stream().collect(Collectors.toMap(x -> x.getId(), x -> x, (x, y) -> x));

            List<String> repairId = mesQmMaintenanceList.stream().map(MesQmMaintenance::getRepairId).collect(Collectors.toList());
            List<Integer> id = mesQmMaintenanceList.stream().map(MesQmMaintenance::getId).collect(Collectors.toList());
            List<MesQmRepair> mesQmRepairList = mesQmRepairMapper.getListByIds(repairId);
            Map<String, MesQmRepair> mesQmRepairMap = mesQmRepairList.stream().collect(Collectors.toMap(x -> x.getId(), x -> x, (x, y) -> x));
            List<MesQmMaintenanceDtl> mesQmMaintenanceDtlList = mesQmMaintenanceDtlMapper.getListByMaintenanceIds(id);

            if (CollectionUtils.isNotEmpty(mesQmMaintenanceDtlList)) {
                mesQmMaintenanceDtlList.stream().forEach(obj -> {
                    ProductRepair repair = new ProductRepair();
                    repair.setReplaceSnCode(obj.getChangeSnCode());

                    if (snCodeDetailMap != null && snCodeDetailMap.containsKey(Integer.parseInt(obj.getMaintenanceId()))) {
                        MesQmMaintenance mesQmMaintenanceVo = snCodeDetailMap.get(obj.getMaintenanceId());
                        repair.setRepairMeasures(mesQmMaintenanceVo.getMaintenanceMeasures());
                        repair.setDefectDescribe(mesQmMaintenanceVo.getFaultDescription());
                        repair.setRepairResult(mesQmMaintenanceVo.getMaintenanceResult());
                        if (mesQmMaintenanceVo.getCdTime() != null) {
                            repair.setRepairTime(sdf.format(mesQmMaintenanceVo.getCdTime()));
                        }
                        repair.setRepairUserName(mesQmMaintenanceVo.getCdName());
                    }
                    if (snCodeDetailMap.containsKey(Integer.parseInt(obj.getMaintenanceId()))) {
                        MesQmMaintenance mesQmMaintenanceVo = snCodeDetailMap.get(obj.getMaintenanceId());
                        repair.setRepairMeasures(mesQmMaintenanceVo.getMaintenanceMeasures());
                        repair.setDefectDescribe(mesQmMaintenanceVo.getFaultDescription());
                        repair.setRepairResult(mesQmMaintenanceVo.getMaintenanceResult());
                        if (mesQmMaintenanceVo.getCdTime() != null) {
                            repair.setRepairTime(sdf.format(mesQmMaintenanceVo.getCdTime()));
                        }
                        repair.setRepairUserName(mesQmMaintenanceVo.getCdName());

                        if (mesQmRepairMap.containsKey(mesQmMaintenanceVo.getRepairId())) {
                            MesQmRepair mesQmRepair = mesQmRepairMap.get(mesQmMaintenanceVo.getRepairId());
                            repair.setRepairNo(mesQmRepair.getCode());
                        }
                    }
                    productRepairList.add(repair);
                });
            }
        }

        ManufacturingProcessInfo info = new ManufacturingProcessInfo();
        info.setProductRepairs(productRepairList);
        info.setProductExams(productExams);
        info.setManufactureBasicInfo(basicInfo);
        return info;
    }

    public KeyAccessoryData getKeyAccessoryData(String snCode) {
        List snCodeList = new ArrayList<>();
        snCodeList.add(snCode);
        //一般只能取到一条
        MesPcbBarCode mesPcbBarCodeBySnCode = mesPcbBarCodeMapper.getMesPcbBarCodeBySnCode(snCode);
        if (mesPcbBarCodeBySnCode == null) {
            return null;
        }
        MesPcbProduceTask mesPcbProduceTask = mesPcbProduceTaskMapper.getListById(mesPcbBarCodeBySnCode.getTaskId());
        if (mesPcbProduceTask == null) {
            return null;
        }
        AccessoryBasicInfo accessoryBasicInfo = new AccessoryBasicInfo();
        accessoryBasicInfo.setFactoryName(mesPcbProduceTask.getFactoryName());
        accessoryBasicInfo.setTaskCode(mesPcbProduceTask.getCode());
        accessoryBasicInfo.setPlanAmount(mesPcbProduceTask.getPlanAmount());
        accessoryBasicInfo.setCompleteAmount(mesPcbProduceTask.getCompleteAmount());
        if (mesPcbProduceTask.getActualEndTime() != null) {
            accessoryBasicInfo.setCompleteTime(sdf.format(mesPcbProduceTask.getActualEndTime()));
        }
        accessoryBasicInfo.setProductCode(mesPcbProduceTask.getProductCode());
        accessoryBasicInfo.setProductName(mesPcbProduceTask.getProductName());
        accessoryBasicInfo.setTaskId(mesPcbProduceTask.getId());

        String produceTime = mesPcbBoxCodeBindMapper.getProduceTime(snCode);
        accessoryBasicInfo.setProduceTime(produceTime);

        List<MesPcbComplete> mesPcbCompleteList = mesPcbCompleteMapper.getByMesPcbCompleteTaskId(accessoryBasicInfo.getTaskId());

        List<AccessoryTask> accessoryTaskList = new ArrayList<>();
        mesPcbCompleteList.stream().forEach(obj -> {
            AccessoryTask task = new AccessoryTask();
            task.setTaskCode(mesPcbProduceTask.getCode());
            task.setProductCode(mesPcbProduceTask.getProductCode());
            task.setProductName(mesPcbProduceTask.getProductName());
            task.setPlanAmount(mesPcbProduceTask.getPlanAmount());
            task.setCompleteAmount(mesPcbProduceTask.getCompleteAmount());
            task.setFactoryName(obj.getCompleteFactoryName());
            task.setReceiveQuantity(obj.getReceiveQty());
            if (obj.getReceiveTime() != null) {
                task.setReceiveTime(sdf.format(obj.getReceiveTime()));
            }
            accessoryTaskList.add(task);
        });

        int sum = accessoryTaskList.stream().filter(x -> x.getReceiveQuantity() != null).mapToInt(AccessoryTask::getReceiveQuantity).sum();
        for (AccessoryTask task : accessoryTaskList) {
            task.setStatus("接收");
        }
        AccessoryTask accessoryTask = accessoryTaskList.get(0);
        if (accessoryTask.getCompleteAmount() > sum) {
            AccessoryTask task = new AccessoryTask();
            task.setTaskCode(accessoryTask.getTaskCode());
            task.setProductCode(accessoryTask.getProductCode());
            task.setProductName(accessoryTask.getProductName());
            task.setPlanAmount(accessoryTask.getPlanAmount());
            task.setCompleteAmount(accessoryTask.getCompleteAmount());
            task.setReceiveQuantity(accessoryTask.getCompleteAmount() - sum);
            task.setStatus("在库");
            accessoryTaskList.add(task);
        }
        KeyAccessoryData res = new KeyAccessoryData();
        res.setAccessoryBasicInfo(accessoryBasicInfo);
        res.setAccessoryTasks(accessoryTaskList);
        return res;
    }
}
